<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- 
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License. 
-->
<html>
<head>
    <link type="text/css" rel="stylesheet" href="https://struts.apache.org/css/default.css">
    <style type="text/css">
        .dp-highlighter {
            width:95% !important;
        }
    </style>
    <style type="text/css">
        .footer {
            background-image:      url('https://cwiki.apache.org/confluence/images/border/border_bottom.gif');
            background-repeat:     repeat-x;
            background-position:   left top;
            padding-top:           4px;
            color:                 #666;
        }
    </style>
    <script type="text/javascript" language="javascript">
        var hide = null;
        var show = null;
        var children = null;

        function init() {
            /* Search form initialization */
            var form = document.forms['search'];
            if (form != null) {
                form.elements['domains'].value = location.hostname;
                form.elements['sitesearch'].value = location.hostname;
            }

            /* Children initialization */
            hide = document.getElementById('hide');
            show = document.getElementById('show');
            children = document.all != null ?
                    document.all['children'] :
                    document.getElementById('children');
            if (children != null) {
                children.style.display = 'none';
                show.style.display = 'inline';
                hide.style.display = 'none';
            }
        }

        function showChildren() {
            children.style.display = 'block';
            show.style.display = 'none';
            hide.style.display = 'inline';
        }

        function hideChildren() {
            children.style.display = 'none';
            show.style.display = 'inline';
            hide.style.display = 'none';
        }
    </script>
    <title>S2-008</title>
</head>
<body onload="init()">
<table border="0" cellpadding="2" cellspacing="0" width="100%">
    <tr class="topBar">
        <td align="left" valign="middle" class="topBarDiv" align="left" nowrap>
            &nbsp;<a href="home.html">Home</a>&nbsp;&gt;&nbsp;<a href="security-bulletins.html">Security Bulletins</a>&nbsp;&gt;&nbsp;<a href="s2-008.html">S2-008</a>
        </td>
        <td align="right" valign="middle" nowrap>
            <form name="search" action="https://www.google.com/search" method="get">
                <input type="hidden" name="ie" value="UTF-8" />
                <input type="hidden" name="oe" value="UTF-8" />
                <input type="hidden" name="domains" value="" />
                <input type="hidden" name="sitesearch" value="" />
                <input type="text" name="q" maxlength="255" value="" />
                <input type="submit" name="btnG" value="Google Search" />
            </form>
        </td>
    </tr>
</table>

<div id="PageContent">
    <div class="pageheader" style="padding: 6px 0px 0px 0px;">
        <!-- We'll enable this once we figure out how to access (and save) the logo resource -->
        <!--img src="/wiki/images/confluence_logo.gif" style="float: left; margin: 4px 4px 4px 10px;" border="0"-->
        <div style="margin: 0px 10px 0px 10px" class="smalltext">Apache Struts 2 Documentation</div>
        <div style="margin: 0px 10px 8px 10px"  class="pagetitle">S2-008</div>

        <div class="greynavbar" align="right" style="padding: 2px 10px; margin: 0px;">
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=27834715">
                <img src="https://cwiki.apache.org/confluence/images/icons/notep_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Edit Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=27834715">Edit Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">
                <img src="https://cwiki.apache.org/confluence/images/icons/browse_space.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Browse Space"></a>
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">Browse Space</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=27834715">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_page_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=27834715">Add Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=27834715">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_blogentry_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add News"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=27834715">Add News</a>
        </div>
    </div>

    <div class="pagecontent">
        <div class="wiki-content">
            <div id="ConfluenceContent"><h2 id="S2-008-Summary">Summary</h2>

<p>
</p><p>Multiple critical vulnerabilities in Struts2</p>

<div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Who should read this </p></th><td colspan="1" rowspan="1" class="confluenceTd"><p> All Struts 2 developers </p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Impact of vulnerability </p></th><td colspan="1" rowspan="1" class="confluenceTd"><p> Remote command execution and arbitrary file overwrite, Strict DMI does not work correctly </p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Maximum security rating </p></th><td colspan="1" rowspan="1" class="confluenceTd"><p> Critical </p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Recommendation </p></th><td colspan="1" rowspan="1" class="confluenceTd"><p> Developers should immediately upgrade to <a shape="rect" class="external-link" href="http://struts.apache.org/download.cgi#struts2311">Struts 2.3.1.1</a> or read the following solution instructions carefully for a configuration change to mitigate the vulnerability </p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Affected Software </p></th><td colspan="1" rowspan="1" class="confluenceTd"><p> Struts 2.1.0 - Struts 2.3.1 </p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Original JIRA Ticket </p></th><td colspan="1" rowspan="1" class="confluenceTd"><p> <a shape="rect" class="external-link" href="https://issues.apache.org/jira/browse/WW-3729">WW-3729</a> </p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Reporter </p></th><td colspan="1" rowspan="1" class="confluenceTd"><p> Johannes Dahse, SEC Consult Vulnerability Lab and Bruce Phillips (blog post) </p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> CVE Identifier </p></th><td colspan="1" rowspan="1" class="confluenceTd"><p>&#160;</p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p> Original Description </p></th><td colspan="1" rowspan="1" class="confluenceTd"><p> <a shape="rect" class="external-link" href="https://www.sec-consult.com/files/20120104-0_Apache_Struts2_Multiple_Critical_Vulnerabilities.txt" rel="nofollow">Reported directly to security@struts.a.o</a> and <a shape="rect" class="external-link" href="http://www.brucephillips.name/blog/index.cfm/2011/2/19/Struts-2-Security-Vulnerability--Dynamic-Method-Invocation" rel="nofollow">Struts 2 Security Vulnerability - Dynamic Method Invocation</a> </p></td></tr></tbody></table></div>


<h2 id="S2-008-Problem">Problem</h2>

<p>To prevent attackers calling arbitrary methods within parameters the flag <code>xwork.MethodAccessor.denyMethodExecution</code> is set to <code>true</code> and the <code>SecurityMemberAccess</code> field <code>allowStaticMethodAccess</code> is set to <code>false</code> by default. Also, to prevent access to context variables an improved character whitelist for parameter names is applied in the <code>ParameterInterceptor</code> since Struts 2.2.1.1:</p>

<p><code>acceptedParamNames = "[a-zA-Z0-9\.][()_']+";</code></p>

<p>Under certain circumstances these restrictions can be bypassed to execute malicious Java code.</p>

<ol><li><strong>Remote command execution in Struts &lt;= 2.2.1.1 (<code>ExceptionDelegator</code>)</strong><br clear="none">
When an exception occurs while applying parameter values to properties, the value is evaluated as an OGNL expression. For example, this occurs when setting a string value to an integer property. Since the values are not filtered an attacker can abuse the power of the OGNL language to execute arbitrary Java code leading to remote command execution. This issue has been reported (<a shape="rect" class="external-link" href="https://issues.apache.org/jira/browse/WW-3668">https://issues.apache.org/jira/browse/WW-3668</a>) and was fixed in Struts 2.2.3.1. However the ability to execute arbitrary Java code has been overlooked.</li><li><strong>Remote command execution in Struts &lt;= 2.3.1 (<code>CookieInterceptor</code>)</strong><br clear="none">
The character whitelist for parameter names is not applied to the <code>CookieInterceptor</code>. When Struts is configured to handle cookie names, an attacker can execute arbitrary system commands with static method access to Java functions. Therefore the flag <code>allowStaticMethodAccess</code> can be set to true within the request.</li><li><strong>Arbitrary File Overwrite in Struts &lt;= 2.3.1 (<code>ParameterInterceptor</code>)</strong><br clear="none">
While accessing the flag <code>allowStaticMethodAccess</code> within parameters is prohibited since Struts 2.2.3.1 an attacker can still access public constructors with only one parameter of type String to create new Java objects and access their setters with only one parameter of type String. This can be abused in example to create and overwrite arbitrary files. To inject forbidden characters into a filename an uninitialized string property can be used.</li><li><strong>Remote command execution in Struts &lt;= 2.3.1 (<code>DebuggingInterceptor</code>)</strong><br clear="none">
While not being a security vulnerability itself, please note that applications running in developer mode and using the <code>DebuggingInterceptor</code> are prone to remote command execution as well. While applications should never run in developer mode during production, developers should be aware that doing so not only has performance issues (as documented) but also a critical security impact.</li></ol>


<h2 id="S2-008-Solution">Solution</h2>

<div class="confluence-information-macro confluence-information-macro-warning"><span class="aui-icon aui-icon-small aui-iconfont-error confluence-information-macro-icon"></span><div class="confluence-information-macro-body">
<p><strong>It is strongly recommended to upgrade to <a shape="rect" class="external-link" href="http://struts.apache.org/download.cgi#struts2311">Struts 2.3.1.1</a></strong><strong>, which contains the corrected classes.</strong></p></div></div>

<p>Update to Struts 2.3.1 and apply a stronger <code>acceptedParamNames</code> filter to the <code>ParameterInterceptor</code> and <code>CookieInterceptor</code>:</p>

<p><code>acceptedParamNames = "[a-zA-Z0-9\.][()_']+";</code></p></div>
        </div>

        
    </div>
</div>
<div class="footer">
    Generated by CXF SiteExporter
</div>
</body>
</html>
